﻿using Sys.Core.Models.Dto;
using Sys.Core.Models.Queries;
using Sys.Core.Models.VO;
using Sys.Core.Providers;
using MiniFox.Components;
using MiniFox.Data.EntityFramework;
using MiniFox.Infrastructure;
using MiniFox.Platform;
using MiniFox.Security.Text;

namespace Sys.Data
{
    [AutoResolve]
    public class UserProvider : EntityDataProvider<PlatformDbContext>, IUserProvider
    {
        private UserVo MappingToVo(SysUser sysUser)
        {
            if (sysUser == null) return null;
            return new UserVo
            {
                UserID = sysUser.UserId,
                UpdateTime = sysUser.UpdateTime,
                Cellphone = sysUser.Cellphone,
                CreateTime = sysUser.CreateTime,
                DisplayName = sysUser.DisplayName,
                LoginName = sysUser.LoginName,
                SecEmail = sysUser.SecEmail,
                UserStatus = Enum.Parse<IdentityStatus>(sysUser.UserStatus),
                Roles = this.GetUserRoles(sysUser.UserId)
            };
        }
        public ResultObject<IEnumerable<UserVo>> Query(PagedQueryObject<UserQuery> query)
        {
            var resultSet = this.PagedQueryExecute<SysUser>(query);
            return resultSet.GetResultObject(sysUser => new UserVo
            {
                UserID = sysUser.UserId,
                DisplayName = sysUser.DisplayName,
                LoginName = sysUser.LoginName,
                Cellphone = sysUser.Cellphone,
                SecEmail = sysUser.SecEmail,
                UserStatus = Enum.Parse<IdentityStatus>(sysUser.UserStatus),
                CreateTime = sysUser.CreateTime,
                UpdateTime = sysUser.UpdateTime,
                Roles = (from r in this.CurrentDbContext.SysRole
                         join ur in this.CurrentDbContext.SysUserRole on r.RoleId equals ur.RoleId
                         where ur.UserId == sysUser.UserId
                         select new RoleVo
                         {
                             RoleID = r.RoleId,
                             RoleName = r.RoleName,
                             Description = r.Description
                         }).ToArray()
            });
        }

        public UserVo GetUser(string userId)
        {
            var sysUser = this.CurrentDbContext.SysUser.SingleOrDefault(u => u.UserId == userId);
            return MappingToVo(sysUser);
        }

        public bool ChangePassword(string userId, Cipher password)
        {
            var sysPwd = this.CurrentDbContext.SysPassword.SingleOrDefault(u => u.UserId == userId);
            sysPwd.Password = password;
            return this.Update(sysPwd) > 0;
        }

        public bool CreateUser(UserDto user, Cipher password)
        {
            SysUser sysUser = new SysUser();
            sysUser.UserId = user.UserID;
            sysUser.DisplayName = user.DisplayName;
            sysUser.LoginName = user.LoginName;
            sysUser.Cellphone = user.Cellphone;
            sysUser.SecEmail = user.SecEmail;
            sysUser.UserStatus = user.UserStatus.ToString();
            sysUser.CreateTime = DateTime.Now;
            sysUser.UpdateTime = DateTime.Now;

            SysPassword sysPassword = new SysPassword();
            sysPassword.UserId = sysUser.UserId;
            sysPassword.Password = password;
            return this.Insert(sysUser, sysPassword) > 0;
        }

        public bool UpdateUser(UserDto user)
        {
            SysUser sysUser = this.CurrentDbContext.SysUser.SingleOrDefault(u => u.UserId == user.UserID);
            sysUser.DisplayName = user.DisplayName;
            sysUser.LoginName = user.LoginName;
            sysUser.Cellphone = user.Cellphone;
            sysUser.SecEmail = user.SecEmail;
            sysUser.UserStatus = user.UserStatus.ToString();
            sysUser.UpdateTime = DateTime.Now;
            return this.Update(sysUser) > 0;
        }

        public bool IsUsedCellphone(string cellphone, string userId = null)
        {
            return string.IsNullOrEmpty(userId) ? this.CurrentDbContext.SysUser.Any(u => u.Cellphone == cellphone) : this.CurrentDbContext.SysUser.Any(u => u.Cellphone == cellphone && u.UserId != userId);
        }

        public bool IsUsedLoginName(string loginName, string userId = null)
        {
            return string.IsNullOrEmpty(userId) ? this.CurrentDbContext.SysUser.Any(u => u.LoginName == loginName) : this.CurrentDbContext.SysUser.Any(u => u.LoginName == loginName && u.UserId != userId);
        }

        public bool IsUsedSecEmail(string secEmail, string userId = null)
        {
            return string.IsNullOrEmpty(userId) ? this.CurrentDbContext.SysUser.Any(u => u.SecEmail == secEmail) : this.CurrentDbContext.SysUser.Any(u => u.SecEmail == secEmail && u.UserId != userId);
        }

        public RoleVo[] GetUserRoles(string userId)
        {
            return (from r in this.CurrentDbContext.SysRole
                    join ur in this.CurrentDbContext.SysUserRole on r.RoleId equals ur.RoleId
                    where ur.UserId == userId
                    select new RoleVo
                    {
                        RoleID = r.RoleId,
                        RoleName = r.RoleName,
                        Description = r.Description
                    }).ToArray();
        }

    }
}
